/*
*	ReadHandle.hpp
*/
#ifndef __READHANDLE_HPP
#define __READHANDLE_HPP

#include <ctime>
#include <string>
#include <ostream>

#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#define separatorChar '\\'
#else
#define separatorChar '/'
#endif

using namespace std;

namespace magus {

//public class ReadHandle
//{

	inline void replaceAll(string &s, char c1, char c2)
	{
	    int pos = 0;
	    while (pos != -1) 
		{
	          pos = s.find(c1, pos);
			  if (pos != -1) {
				 s[pos++] = c2;
			  }
	    }
	}

	inline void replaceAll(string &s, char *src, char *dst)
	{
	    int pos = 0;
	 	int l1 = strlen(src);
	 	int l2 = strlen(dst);
	    while (pos != -1)
	    {
	          pos = s.find(src, pos);
			  if (pos != -1) {
	             s.replace(pos, l1, dst, l2);
			     pos += l2;
			  }
	    }
	}
	
	inline void removeDelim(string& s, char delim)
	{
	    string::size_type pos = 0;
	 	int len = 1; // strlen(delim);
	    while (pos != string::npos)
	    {
	          pos = s.find(delim, pos);
	          if(pos != string::npos)
	             s.erase(pos, len);
	    }
	}

	inline void trimLeft(std::string& s)
	{
		int len = s.size();
		int i = 0;
		while (i < len && isspace(s[i] & 0xff))
			++i;
		s.erase(0, i);
	}

	inline void trimRight(std::string& s)
	{
		int len = s.size();
		int i = len;
	    while (i > 0 && isspace(s[i-1] & 0xff)) 
			--i;   
		s.erase(i, len-i);	
	}
	
	inline void trimString(std::string &s)
	{
		trimLeft(s);
		trimRight(s);
	}

	inline int sscan(string &s, char delim, int num, string ss[])
	{
		string::size_type cp, pos;
		int i = 0;
		pos = 0;
		for (i=0; i<num; i++) {
			cp = s.find(delim, pos);
			if (cp == string::npos){
				ss[i++] = s.substr(pos);
				pos = s.length();	
				break;
			}
			ss[i] = s.substr(pos, cp-pos);
			pos = cp + 1;
		}
		s = s.substr(pos);   // return remainder
		return i;
	}

	inline int sscan(string &s, int num, string ss[])
	{
		int cp, pos, len, i;

		pos = 0;
		len = s.length();
		for (i=0; i<num; i++) {
			// left trim
			while (pos < len && isspace(s[pos] & 0xff))
				++pos;
			if (pos == len) break;
			
			// find next space
			cp = pos;
			while (cp < len && !isspace(s[cp] & 0xff))
				++cp;
				
			ss[i] = s.substr(pos, cp-pos);
			pos = cp;
		}
		s = s.substr(pos);   // return remainder
		return i;
	}
	
	inline string baseNameOf(string &src)
	{
		string s = src;
		int cp = src.find_last_of(separatorChar);
		if (cp != -1)
			s = src.substr(cp+1);
		cp = s.find_last_of('.');
		if (cp != -1) {
			s = s.substr(0, cp);
		}
		return s;
	}
	
	inline void toUpper(string& str)
	{
        int i = 0;
	int len = str.length();
        while (i < len) {
            str[i] = toupper(str[i]);
			++i;
		}
	}

	inline void toLower(string& str)
	{
        int i = 0;
	int len = str.length();
        while (i < len) {
            str[i] = tolower(str[i]);
			++i;
		}
	}

	inline void strupper(char *str)
	{
	  if (!str) return;
	  while (*str) {
		  *str = toupper(*str);
		  ++str;
	  }
	}

	inline void strlower(char *str)
	{
	  if (!str) return;
	  while (*str) {
		  *str = tolower(*str);
		  ++str;
	  }
	}

	inline string parseString(char *buf, int off, int len) {
        int l = 0;
        for (int i=0; i<len; i++) {
            if (buf[off+i] == 0)
                break;
            l++;
        }
        return string(buf, off, l);
    }

	inline int ubyteGet(const char* buf, int i) 
	{
		return (buf[i] & 0xff);
	}

	inline int byteGet(const char* buf, int i) 
	{
		return (buf[i]);
	}

	inline int ushortGet(const char* buf, int i, int bigEndian=1) 
	{
	    if (bigEndian)
		    return ((buf[i] & 0xff) << 8) + (buf[i+1] & 0xff);
		else
		    return ((buf[i+1] & 0xff) << 8) + (buf[i] & 0xff);
	}

	inline int shortGet(const char* buf, int i, int bigEndian=1) 
	{
	    if (bigEndian)
		    return  (buf[i] << 8) + (buf[i+1] & 0xff);
		else
		    return  (buf[i+1] << 8) + (buf[i] & 0xff);
	}

	inline int longGet(const char* buf, int i, int bigEndian=1) 
	{
	    if (bigEndian)
    		return ((buf[i] & 0xff) << 24) + ((buf[i+1] & 0xff) << 16)
    			+ ((buf[i+2] & 0xff) << 8) + (buf[i+3] & 0xff);
        else
    		return ((buf[i+3] & 0xff) << 24) + ((buf[i+2] & 0xff) << 16)
    			+ ((buf[i+1] & 0xff) << 8) + (buf[i] & 0xff);
	}

	inline float floatGet(const char* buf, int i, int bigEndian=1) 
	{
		int j = longGet(buf, i, bigEndian);
		return *(float *)&j;
	}

	inline void shortStore(char *buf, int i)
	{
		*buf++ = (char)(i >> 8);
		*buf = (char)i;
	}
	
	inline void longStore(char *buf, int i)
	{
		*buf++ = (char)(i >> 24);
		*buf++ = (char)(i >> 16);
		*buf++ = (char)(i >> 8);
		*buf = (char)i;
	}

	inline void floatStore(char *buf, float f)
	{
		int i = *(int *)&f;
		*buf++ = (char)(i >> 24);
		*buf++ = (char)(i >> 16);
		*buf++ = (char)(i >> 8);
		*buf = (char)i;
	}

	inline void timeStore(char *buf, time_t t)
	{
		*buf++ = (t >> 24);
		*buf++ = (t >> 16);
		*buf++ = (t >> 8);
		*buf = t;
	}

    inline void decodeTime(time_t t, int* yy, int* mm, int* dd, 
    		int* hh, int* mi, int* ss)
    {
	#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
		struct tm *tp;
		tp = localtime(&t);
		*yy = tp->tm_year + 1900;
		*mm = tp->tm_mon + 1;
		*dd = tp->tm_mday;
		*hh = tp->tm_hour;
		*mi = tp->tm_min;
		*ss = tp->tm_sec;
	#else
		struct tm tms;
		localtime_r(&t, &tms);
		*yy = tms.tm_year + 1900;
		*mm = tms.tm_mon + 1;
		*dd = tms.tm_mday;
		*hh = tms.tm_hour;
		*mi = tms.tm_min;
		*ss = tms.tm_sec;
	#endif		
    }

    inline time_t encodeTime(int yy, int mm, int dd, int hh, int mi, int ss)
    {
    	struct tm tms;
    	tms.tm_year = yy - 1900;
    	tms.tm_mon = mm - 1;
    	tms.tm_mday = dd;
    	tms.tm_hour = hh;
    	tms.tm_min = mi;
    	tms.tm_sec = ss;
    	tms.tm_isdst = 0;
    	return mktime(&tms);
    }

	inline void writeByte(ostream &out, int i)
	{
		char c = (i & 0xff);
		out.write(&c, 1);
	}

	inline void writeShort(ostream &out, int i)
	{
		char buf[2];
		shortStore(buf, i);
		out.write(buf, 2);
	}

	inline void writeInt(ostream &out, int i)
	{
		char buf[4];
		longStore(buf, i);
		out.write(buf, 4);
	}

	inline void writeFloat(ostream &out, float f)
	{
		char buf[4];
		floatStore(buf, f);
		out.write(buf, 4);
	}

	inline void writeUTF(ostream &out, const string &s)
	{
		char buf[2];
		int len = (short)s.length();
		shortStore(buf, len);
		out.write(buf, 2);
		out << s;
	}

	inline void writeUTF(ostream &out, const char *str, int len)
	{
		char buf[2];
		shortStore(buf, len);
		out.write(buf, 2);
		out.write(str, len);
	}

//} // class
} // namespace magus

#endif  /* __READHANDLE_HPP */

